/**
  SUNNY project, Anyang Normal University, IMP-CAS
  \class TASparseVec
  \brief Serving as a column for sparse matrix, inherited from ROOT main I/O class
   - TTree, which is dedicated to handle large amount of data. Note that one object
  stands for one column in a sparse matrix.
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021/02/10
  \date Last modified: 2022/07/25 by SUN Yazhou
  \copyright 2020-2021 SUN Yazhou
  \copyright SUNNY project, Anyang Normal University, IMP-CAS
*/

#ifndef _TASparseVec_h_
#define _TASparseVec_h_

#include <string>
#include "TATreeCol.h"
#include "TABit.h"

class TASparseMatrix;

using std::string;

class TASparseVec : public TATreeCol{
public:
  TASparseVec(const string &name = "v", const string &title = "");
  TASparseVec(const TASparseVec &v);
  TASparseVec(TASparseVec &&v); ///< the move constructor
  TASparseVec &operator=(const TASparseVec &v); ///< copy v to this
  virtual ~TASparseVec(){}

  virtual void SetBranchAddress() override;
  virtual void CreateBranch() override;
  virtual void CopyFill(const TATreeCol *t) override;
  double GetValue(ull r) const; ///< get the value of index (row) r
  double operator[](ull r) const{ return GetValue(r); }
  ull GetRow(ull entryIndex) const; ///< \retval fR of entryIndex
  void Fill(ull r, double v);
  using TATreeCol::Fill;
  void SelfAdd(double k, const TASparseVec &v); ///<\retval this += k*v
  void Scale(double v, TASparseVec &r) const; ///< r = v*this
  double DotProduct(const TASparseVec &v) const; ///< \retval (*this)*v
  void Purify(const TASparseVec &q); ///< remove q bits from r: r-= |q><q|r>
  /// remove Q=(q1,q2..qn) bits from r: r-= \sum_q{|q><q|r>}
  void Purify(const TASparseMatrix &Q);
  ull GetMaxRow() const; ///< \retval row of the last (non-zero) entry
  double norm() const; ///< \retval sqrt(norm2)
  double norm2() const; ///< \retval (*this)*(*this)
  void Print() const;
  void PrintInC(ull maxLen) const; ///< print in C/C++ form
  void normalize();
  static double trim(double v); // trim v to zero if fabs(v) < epsilon (e.g. 1.e-16)

protected:
  ull fIndex; ///< entry index
  ull fR; ///< row number
  double fV; ///< the matrix element
};

#endif
